import { Matrix4 } from "../../utils/Matrix4";
import { Primitives } from "../../utils/Primitives";
import { TextrueUtil } from "../../utils/TextureUtil";
import { Util } from "../../utils/Util";
import { WebGLUtil } from "../../utils/WebGLUtil";
import { Render } from "../Render";
import { WebglTemplateBase } from "../template/WebglTemplateBase";

/*
 * @Author: Snow
 * @Date: 2021-10-11 20:35:00
 * @Description: 数据像素
 */
export class TextureDataPix extends WebglTemplateBase {
    protected override initProgram(): void {
        this.vsSource = `
            attribute vec4 a_position;
            attribute vec2 a_texcoord;
            
            uniform mat4 u_matrix;
            
            varying vec2 v_texcoord;
            
            void main() {
                // Multiply the position by the matrix.
                gl_Position = u_matrix * a_position;
                
                ///纹理映射的透视纠正  为什么除以W  纹理就扭曲了呢
                //除以 W 意味值 gl_Position.w 始终为 1，X, Y, 和 Z 不会有什么影响，因为WebGL也会默认做除法。
                gl_Position /= gl_Position.w;
                // Pass the texcoord to the fragment shader.
                v_texcoord = a_texcoord;
            }
        `;

        this.fsSource = `
            precision mediump float;

            // Passed in from the vertex shader.
            varying vec2 v_texcoord;
            
            // The texture.
            uniform sampler2D u_texture;
            
            void main() {
                gl_FragColor = texture2D(u_texture, v_texcoord);
            }
        `;
        super.initProgram();
    }

    protected override initBuffers(): void {
        super.initBuffers();
        const gl = Render.GL;

        var positions = [
            -0.5, -0.5, -0.5,
            -0.5, 0.5, -0.5,
            0.5, -0.5, -0.5,
            -0.5, 0.5, -0.5,
            0.5, 0.5, -0.5,
            0.5, -0.5, -0.5,

            -0.5, -0.5, 0.5,
            0.5, -0.5, 0.5,
            -0.5, 0.5, 0.5,
            -0.5, 0.5, 0.5,
            0.5, -0.5, 0.5,
            0.5, 0.5, 0.5,

            -0.5, 0.5, -0.5,
            -0.5, 0.5, 0.5,
            0.5, 0.5, -0.5,
            -0.5, 0.5, 0.5,
            0.5, 0.5, 0.5,
            0.5, 0.5, -0.5,

            -0.5, -0.5, -0.5,
            0.5, -0.5, -0.5,
            -0.5, -0.5, 0.5,
            -0.5, -0.5, 0.5,
            0.5, -0.5, -0.5,
            0.5, -0.5, 0.5,

            -0.5, -0.5, -0.5,
            -0.5, -0.5, 0.5,
            -0.5, 0.5, -0.5,
            -0.5, -0.5, 0.5,
            -0.5, 0.5, 0.5,
            -0.5, 0.5, -0.5,

            0.5, -0.5, -0.5,
            0.5, 0.5, -0.5,
            0.5, -0.5, 0.5,
            0.5, -0.5, 0.5,
            0.5, 0.5, -0.5,
            0.5, 0.5, 0.5,

        ];

        // let tempMatrix = Matrix4.translation(-50, -75, -15);

        // for (let ii = 0; ii < positions.length; ii += 3) {
        //     var vector = Matrix4.transformPoint(tempMatrix, [positions[ii + 0], positions[ii + 1], positions[ii + 2], 1]);
        //     positions[ii + 0] = vector[0];
        //     positions[ii + 1] = vector[1];
        //     positions[ii + 2] = vector[2];
        // }

        let texcoords = [
            0, 0,
            0, 1,
            1, 0,
            0, 1,
            1, 1,
            1, 0,

            0, 0,
            0, 1,
            1, 0,
            1, 0,
            0, 1,
            1, 1,

            0, 0,
            0, 1,
            1, 0,
            0, 1,
            1, 1,
            1, 0,

            0, 0,
            0, 1,
            1, 0,
            1, 0,
            0, 1,
            1, 1,

            0, 0,
            0, 1,
            1, 0,
            0, 1,
            1, 1,
            1, 0,

            0, 0,
            0, 1,
            1, 0,
            1, 0,
            0, 1,
            1, 1,
        ];


        // an indexed quad
        let arrays = {
            position: { numComponents: 3, data: positions, },
            texcoord: { numComponents: 2, data: texcoords, },
        };


        let bufferInfo = WebGLUtil.createBufferInfoFromArrays(gl, arrays);

        let cameraAngleRadians = Util.degToRad(0);
        let fieldOfViewRadians = Util.degToRad(60);
        let cameraHeight = 50;

        let textures = [
            TextrueUtil.makeStripeTexture(gl, { color1: "#FFF", color2: "#CCC", }),
            TextrueUtil.makeCheckerTexture(gl, { color1: "#FFF", color2: "#CCC", }),
            TextrueUtil.makeCircleTexture(gl, { color1: "#FFF", color2: "#CCC", }),
        ];


        // 设置读取数据长度
        /*
        WebGL中有一种首次创建OpenGL后的模糊设定， 计算机有时在数据为某些特定大小时速度会快一些， 
        例如一次拷贝2，4 或 8 个字节比一次拷贝 1 个字节要快， WebGL默认使用 4 字节长度，
        所以它期望每一行数据是多个 4 字节数据（最后一行除外）。
        我们之前的数据每行只有 3 个字节，总共为 6 字节， 但是 WebGL 试图在第一行获取 4 个字节，
        第二行获取 3 个字节， 总共 7 个字节，所以会出现这样的报错。
        我们可以告诉WebGL一次处理 1 个字节
        */
        const alignment = 1;
        gl.pixelStorei(gl.UNPACK_ALIGNMENT, alignment);

        // Create a texture.
        let texture = gl.createTexture();
        gl.bindTexture(gl.TEXTURE_2D, texture);
        // Fill the texture with a 1x1 blue pixel.
        // gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, 3, 2, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE,
        //     new Uint8Array([128,  64, 128, 0, 192,  0,]));
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, 3, 2, 0, gl.RGB, gl.UNSIGNED_BYTE,
            new Uint8Array([128,  64, 128, 
                            0, 192,  0,
                            128,  64, 128,
                            0, 192,  0,
                            128,  64, 128, 
                            0, 192,  0,]));
        // Asynchronously load an image
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        //gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);

        // let image = new Image();
        // //image.src = "f-texture.png";
        // image.src = "noodles.jpg";
        // image.addEventListener('load', function () {
        //     // Now that the image has loaded make copy it to the texture.
        //     gl.bindTexture(gl.TEXTURE_2D, texture);
        //     gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
        //     if (Util.isPowerOf2(image.width) && Util.isPowerOf2(image.height)) {
        //         gl.generateMipmap(gl.TEXTURE_2D);
        //     } else {
        //         // 不是 2 的幂，关闭贴图并设置包裹模式为到边缘
        //         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        //         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        //         gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        //     }

        // });

        let uniforms = {
            u_texture: texture,
            u_matrix: null,
        }


        let drawScene = () => {
            let time = this.ts;
            time = time;
            WebGLUtil.resizeCanvasToMatchDisplaySize(gl);
            // Clear the canvas AND the depth buffer.
            gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

            // Compute the projection matrix
            let aspect = gl.canvas.clientWidth / gl.canvas.clientHeight;
            var projectionMatrix = Matrix4.perspective(fieldOfViewRadians, aspect, 1, 2000);

            // Compute the camera's matrix using look at.
            let cameraPosition = [0, 0, 3];
            let target = [0, 0, 0];
            let up = [0, 1, 0];
            let cameraMatrix = Matrix4.lookAt(cameraPosition, target, up);

            // Make a view matrix from the camera matrix.
            let viewMatrix = Matrix4.invert(cameraMatrix);

            let viewProjectionMatrix = Matrix4.multiply(projectionMatrix, viewMatrix);

            let sphereXRotation = time;
            let sphereYRotation = time;
            let cubeXRotation = -time;
            let cubeYRotation = time;
            let coneXRotation = time;
            let coneYRotation = -time;

            gl.useProgram(this.programInfo.program);

            let computeMatrix = (viewProjectionMatrix, translation, xRotation, yRotation): number[] => {
                let matrix = Matrix4.multiply(viewProjectionMatrix, Matrix4.translation(
                    translation[0],
                    translation[1],
                    translation[2]));
                matrix = matrix = Matrix4.multiply(matrix, Matrix4.rotateX(xRotation));
                return matrix = matrix = Matrix4.multiply(matrix, Matrix4.rotateY(yRotation));
            }

            // Setup all the needed buffers and attributes.
            WebGLUtil.setBuffersAndAttributes(gl, this.programInfo, bufferInfo);

            uniforms.u_matrix = computeMatrix(viewProjectionMatrix, [0, 0, 0], sphereXRotation, sphereYRotation)

            // Set the uniforms that are the same for all objects.
            WebGLUtil.setUniforms(this.programInfo, uniforms);

            // Draw the geometry.
            gl.drawArrays(gl.TRIANGLES, 0, bufferInfo.numElements);
        }
        this.draw = drawScene;
    }
}